package teamproject.visualization.gui.behaviors;

import java.awt.AWTEvent;
import java.awt.event.KeyEvent;
import java.util.Enumeration;

import javax.media.j3d.Behavior;
import javax.media.j3d.Bounds;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnAWTEvent;
import javax.media.j3d.WakeupOnElapsedFrames;
import javax.media.j3d.WakeupOr;
import javax.vecmath.Vector3d;

import teamproject.visualization.gui.SpaceBarProcessor;
import teamproject.visualization.gui.Visualizer;

import com.sun.j3d.utils.geometry.Cylinder;

public class BufferMoveBehavior extends Behavior implements Resettable {

	private Enumeration<Cylinder> children;
	private TransformGroup target;
	private Transform3D transform = new Transform3D();
	private Vector3d vector = new Vector3d();
	private Cylinder shape;
	private SpaceBarProcessor sbp;

	private int upperTimeBound;
	private int counter = 0;
	private float height;

	private WakeupCriterion[] warray;
	private WakeupOr criterion;
	private WakeupOnAWTEvent wakeupevent;
	private WakeupCriterion wakeupcriterion;
	private AWTEvent[] events;

	public BufferMoveBehavior(TransformGroup target, int upperTimeBound,
			Bounds bounds) {
		this.target = target;
		this.upperTimeBound = upperTimeBound;
		this.sbp = new SpaceBarProcessor();

		setSchedulingBounds(bounds);
	}

	@SuppressWarnings("unchecked")
	private void doProcess() {
		if (!sbp.hasStopped()) {
			if (counter < upperTimeBound) {
				children = target.getAllChildren();

				while (children.hasMoreElements()) {
					Object obj = children.nextElement();
					if (obj instanceof Cylinder)
						shape = (Cylinder) obj;
				}

				height = shape.getHeight();
				vector.x = 0.0;
				vector.y = height / 2.0;
				vector.z = 0.0;

				transform.setTranslation(vector);
				target.setTransform(transform);

				counter++;
			}
		}
	}

	@Override
	public void initialize() {
		warray = new WakeupCriterion[2];

		warray[0] = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
		warray[1] = new WakeupOnElapsedFrames(Visualizer.SPEEDFACTOR);

		criterion = new WakeupOr(warray);

		wakeupOn(criterion);
	}

	@SuppressWarnings("rawtypes")
	@Override
	public void processStimulus(Enumeration criteria) {

		while (criteria.hasMoreElements()) {
			wakeupcriterion = (WakeupCriterion) criteria.nextElement();
			if (wakeupcriterion instanceof WakeupOnAWTEvent) {
				wakeupevent = (WakeupOnAWTEvent) wakeupcriterion;
				events = wakeupevent.getAWTEvent();
				sbp.processAWTEvents(events);
			} else if (wakeupcriterion instanceof WakeupOnElapsedFrames) {
				doProcess();
			}
		}

		wakeupOn(criterion);
	}

	@Override
	public void reset() {
		vector.x = 0;
		vector.y = 0;
		vector.z = 0;

		transform.setTranslation(vector);
		target.setTransform(transform);

		counter = 0;
	}
}
